package com.qianji.petmall.product.web;

import com.qianji.petmall.product.entity.CategoryEntity;
import com.qianji.petmall.product.service.CategoryService;
import com.qianji.petmall.product.vo.CateLog2Vo;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author liang zai
 * @date 2022/2/11 14:34
 * @description
 */
@Controller
public class IndexController {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedissonClient redisson;

    @Autowired
    private StringRedisTemplate redisTemplate;
    @GetMapping({"/","index.html"})
    public String getIndex(Model model){
        List<CategoryEntity> list = categoryService.getLevelOne();
        model.addAttribute("categers",list);
        return "index";
    }

    @ResponseBody
    @GetMapping("/index/catalog.json")
    public Map<String, List<CateLog2Vo>> getCateLogJson(){
        Map<String, List<CateLog2Vo>> cateLogJson = categoryService.getCatLogJson();
        return cateLogJson;
    }

    @ResponseBody
    @GetMapping("/hello")
    public String hello(){
        RLock lock = redisson.getLock("lock");
        //加锁
        lock.lock();//阻塞式等待，默认加锁都是30s过期时间
              lock.lock();      //如果中途负责储存这个分布式锁的Redisson节点宕机，redisson提供了一个看门狗，会在宕机前自动对锁续期10s，每隔10s自动续期，不断的延长锁的有效期，避免死锁
        lock.lock(10, TimeUnit.SECONDS);//10s自动解锁  使用的时候自动解锁时间一点要大于业务执行时间
                                                  //时间到了后看门狗不会自动续期
        try {
            System.out.println("加锁成功"+Thread.currentThread().getId());
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("释放锁"+Thread.currentThread().getId());
            //解锁
            lock.unlock();
        }

        return "hello";
    }

    @ResponseBody
    @GetMapping("/write")
    public String write(){
        String s="";
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("lock");
        RLock rLock = readWriteLock.writeLock();//保证一定能拿到最新的数据，修改数据的时候，写锁属于排他锁（读锁属于共享锁）
                                                //写锁没释放就必须等待
        try {
            //添加一个写锁
            rLock.lock();
            s = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set("token",s);
            System.out.println("写锁加载成功"+Thread.currentThread().getId());
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rLock.unlock();
            System.out.println("写锁释放"+Thread.currentThread().getId());
        }
        return s;
    }

    @ResponseBody
    @GetMapping("/read")
    public String read(){
        String s="";
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("lock");
        RLock rLock = readWriteLock.readLock();
        try {
            s = UUID.randomUUID().toString();
            redisTemplate.opsForValue().get("token");
            //添加一个读锁
            rLock.lock();
            System.out.println("读锁加载成功"+Thread.currentThread().getId());
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rLock.unlock();
            System.out.println("读锁释放"+Thread.currentThread().getId());
        }
        return s;
    }

    /**
     *停车
     * 有车位可以停
     */
    @ResponseBody
    @GetMapping("/park")
    public String park(){
        RSemaphore port = redisson.getSemaphore("port");
//      port.acquire();
        boolean b = port.tryAcquire();//非阻塞式的，如果有空余的则会进入，没有则返回false
        return "ok=》》"+b;
    }

    @ResponseBody
    @GetMapping("/go")
    public String go(){
        RSemaphore port = redisson.getSemaphore("port");
        port.release();
        return "ok";
    }

    /**
     * 放假、锁门
     * 全部走了才可以锁门
     */
    @ResponseBody
    @GetMapping("/lockDoor")
    public String lockDoor(){
        RCountDownLatch door = redisson.getCountDownLatch("door");
        try {
            door.trySetCount(5);
            door.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "放假了锁门";
    }

    @ResponseBody
    @GetMapping("/gogo/{id}")
    public String gogo(@PathVariable("id") Long id){
        RCountDownLatch door = redisson.getCountDownLatch("door");
        door.countDown();
        return id+"班下课了";
    }
}
